/**
 * Copyright 2009 cestum.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.cestum.cave.ui.components{
	
	import flash.display.Sprite;
    import flash.display.DisplayObject;
    import flash.display.DisplayObjectContainer;
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.events.Event;
    import mx.events.FlexEvent;
    import flash.geom.Matrix;
    import flash.geom.Rectangle;
    import flash.display.Graphics;
    import flash.display.GradientType;
    import flash.display.Shape;
    import flash.geom.Point;
    import flash.display.BlendMode;
    import mx.controls.Alert;


	/*
	 * originally written by http://lab.benstucki.net/archives/reflectionexplorer/srcview/
	 * sligtly modified for AS3 projects, and the tastes of sakri.net ;)
	 */
	public class Reflection extends Sprite{
		
        private var _target:DisplayObject;
        public function set target(t:DisplayObject):void{
        	if(_reparent){
        		throw(new Error("CANNOT CHANGE REFLECTION TARGET IF init() WAS CALLED WITH reparenting=true"));
        	}else{
		    	_target=t;
		    	render();
        	}
        }
        public function get target():DisplayObject{
        	return _target;
        }
                
        private var _holder:Bitmap;
        private var _reparent:Boolean=false;
        
        private var _fade_from:Number=0.3;
        private var _fade_to:Number=0;
        private var _fade_center:Number=0.5;
        private var _skew_x:Number=0;
        private var _scale_y:Number=1;
        
        public function Reflection():void{
        	super();
        }
        
        /*
         * reparent means that the target display object is placed on the timeline of the reflection
         * from this point on the "client" can manipulate position of parent and reflection using the Reflection instances properties.
         */
        public function init(target:DisplayObject=null,reparent:Boolean=false,offset:Number=0):void{
        	if(target!=null){
	        	_target=target;
	        	if(reparent){
	        		_reparent=true;
	        		var target_parent:DisplayObjectContainer=_target.parent;
	        		var child_index:uint=target_parent.getChildIndex(_target);
	        		addChild(_target);
	        		target_parent.addChildAt(this,child_index);
	        		_holder.y=_target.y+target.height+offset;
	        	}
        	}
            render();
       	}

		private var _num_renders:Number=0;;
        public function render(e:Event=null):void{
        	if(_target==null || !_target.width || !_target.height)return;
        	_num_renders++;
        	if(_holder!=null)removeChild(_holder);
         	_holder=new Bitmap(new BitmapData(_target.width,_target.height,true,0));
            addChildAt(_holder,0);
            
            //draw reflection
            var reflection:BitmapData=new BitmapData(_target.width,_target.height,true,0);
            var matrix:Matrix = new Matrix(1,0,_skew_x, -_scale_y,0,_target.height );
            var rectangle:Rectangle=new Rectangle(0,0,width,height*(2-_scale_y));
            var delta:Point=matrix.transformPoint(new Point(0,_target.height));
            matrix.tx=delta.x*-1;
            matrix.ty=(delta.y-_target.height)*-1;
            reflection.draw(_target,matrix,null,null,rectangle,true);
            
            //add fade
            var shape:Shape = new Shape();
            var gradientMatrix:Matrix = new Matrix();
            gradientMatrix.createGradientBox(this.width,this.height, 0.5*Math.PI);
            shape.graphics.beginGradientFill(GradientType.LINEAR,new Array(0,0,0),new Array(_fade_from,(_fade_from-_fade_to)/2,_fade_to), new Array(0,0xFF*_fade_center,0xFF), gradientMatrix)
            shape.graphics.drawRect(0, 0, this.width, this.height);
            shape.graphics.endFill();
            reflection.draw(shape, null, null, BlendMode.ALPHA);
            
            //apply result
            _holder.bitmapData.dispose();
            _holder.bitmapData=reflection;

        }
        
        override public function toString():String{
        	return "num_renders:"+_num_renders;
        }
		
	}
}